package com.d5power.graphics
{
	
	import com.d5power.D5Game;
	import com.d5power.net.D5StepLoader;
	import com.d5power.utils.UVData;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.GradientType;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	
	public class Swf2p5 implements ISwfDisplayer
	{
		private var _lib:Array;
		private var _list:Object;
		private var _time:int = 0;
		private var _bmd:Bitmap;
		private var _frame:int = 0;
		private var _shadow:Shape;
		private var _direction:int;
		private var _nowFrame:uint;
		private var _loop:Boolean=true;
		private var _totalFrame:uint;
		private var _offsetX:int;
		private var _offsetY:int;
		
		private var _swfPath:String;
		
		private var _renderFun:Function;
		private var _resetMartix:Function;
		private var _uvMode:Boolean;
		/**
		 * 阴影缩放系数，请根据实际项目情况修改
		 */ 
		protected var _shadowScale:Number = 0.05;
		
		private var _onResReady:Function;
		
		private var _playSpeed:uint;
		
		private var _uvList:Array;
		
		private static const transformMartix:Matrix = new Matrix();
		
		private var _2ddriver:Boolean=false;
		
		public function Swf2p5()
		{
			_bmd = new Bitmap();
			super();
		}
		
		public function set onReady(f:Function):void
		{
			_onResReady = f;
		}
		
		public function get swfDir():String
		{
			var index:int = _swfPath.lastIndexOf('/');
			return index==-1 ? '' : _swfPath.substr(0,index);
		}
		
		public function get maxFrame():uint
		{
			return _list.length;
		}
		
		public function get nowFrame():uint
		{
			return _nowFrame;
		}
		
		public function get swfPath():String
		{
			return _swfPath;
		}
		
		public function get rendering():BitmapData
		{
			return _list ? _list[_nowFrame] : null;
		}
		
		public function resetFrame():void
		{
			
		}
		
		public function dispose():void
		{
			_onResReady = null;
			_bmd.bitmapData=null;
			_list = null;
		}
		
		public function get monitor():Bitmap
		{
			return _bmd;
		}
		
		public function get shadow():Shape
		{
			return _shadow;
		}
		
		public function set direction(v:int):void
		{
			if(_direction==v || (_2ddriver && (v==0 || v==4))) return;
			
			
			if(v*_direction<=0)
			{
				_direction = v;
				if(!_uvMode && _resetMartix!=null)_resetMartix();
			}else{
				_direction = v;
			}
			
			
			
			if(_lib==null) return;
			
			updateList();
		}
		
		public function get renderDirection():int
		{
			if(_2ddriver) return 0;
			return _direction>0 ? _direction : -_direction;
		}
		
		public function set loop(b:Boolean):void
		{
			_loop = b;
		}
		
		public function set action(v:int):void
		{
			
		}
		
		public function get playFrame():uint
		{
			return _nowFrame;
		}
		
		public function get totalFrame():uint
		{
			return _totalFrame;
		}
		
		private var _frameBack:int;
		private var _frameBackFun:Function;
		public function changeSWF(file:String,onLoaded:Function=null,frame:int=-1,framebak:Function=null):void
		{
			_swfPath = file;
			_frameBack = frame;
			_frameBackFun = framebak;
			_onResReady = onLoaded;
			D5StepLoader.me.addLoad(D5Game.me.projPath+file,setSWF,true,D5StepLoader.TYPE_SWF);
		}
		
		public function changeSWFJson(file:String,onLoaded:Function=null,frame:int=-1,framebak:Function=null):void
		{
			_swfPath = file;
			_frameBack = frame;
			_frameBackFun = framebak;
			_onResReady = onLoaded;
			D5StepLoader.me.addLoad(D5Game.me.projPath+file,loadJSONConfig,true,D5StepLoader.TYPE_BITMAP);
		}
		
		private var resBitmap:BitmapData;
		private function loadJSONConfig(res:Bitmap):void
		{
			if(res==null)
			{
				trace("无法加载角色素材"+_swfPath);
				return;
			}
			
			resBitmap = res.bitmapData;
			var jsonPath:String = _swfPath.substr(0,_swfPath.length-3)+"json";
			D5StepLoader.me.addLoad(D5Game.me.projPath+jsonPath,setSWFJson,true,D5StepLoader.TYPE_STRING);
		}
		
		private function setSWFJson(json_res:String):void
		{
			if(json_res==null)
			{
				trace("角色素材"+_swfPath+"所需要的配置文件无法加载");
				return;
			}
			
			try
			{
				var data:Object = JSON.parse(json_res);
			}catch(e:Error){
				trace("角色素材"+_swfPath+"所需要的配置文件格式不正确。");
			}
			
			var res:BitmapData = resBitmap;
			var per:uint = data.Frame;
			var dir:uint = data.Direction;
			var frameW:uint = data.FrameWidth;
			var frameH:uint = data.FrameHeight;
			
			var temp_bd:BitmapData;
			//var mirror_bd:BitmapData = new BitmapData(frameW, frameH, true, 0);
			//var matrix:Matrix = new Matrix(-1, 0, 0, 1, frameW, 0);
			var rect:Rectangle = new Rectangle();
			var p:Point = new Point();
			var list:Array = new Array();
			//var listMirror:Array = new Array();

			var uvMode:Boolean = data.uv!=null;
			uvMode ? trace("This is a uvMode graphics resource.") : trace("This is not a uvMode graphics resource.");
			
			var uvArr:Array;
			if(uvMode)
			{
				uvArr = new Array();
				for each(var obj:Object in data.uv)
				{
					uvArr.push(obj);
				}
			}
			
			rect.width = frameW;
			rect.height = frameH;
			
			var lineArr:Vector.<BitmapData>;
			//var mirrorArr:Vector.<BitmapData>;
			
			var count:uint = 0;
			for(var py:uint = 0;py<dir;py++)
			{
				lineArr = new Vector.<BitmapData>;
				//mirrorArr = new Vector.<BitmapData>;
				
				for(var px:uint = 0;px<per;px++)
				{
					rect.x = px*frameW;
					rect.y = py*frameH;
					
					if(uvMode && uvArr[py*per+px]!=null)
					{
						rect.x+=int(uvArr[py*per+px].x);
						rect.y+=int(uvArr[py*per+px].y);
						rect.width = int(uvArr[py*per+px].width);
						rect.height = int(uvArr[py*per+px].height);
					}
					
					temp_bd = new BitmapData(rect.width, rect.height, true, 0);
					temp_bd.copyPixels(res, rect, p);
					
//					if (_mirror.indexOf(py.toString())!=-1)
//					{
//						mirror_bd = new BitmapData(rect.width, rect.height, true, 0);
//						mirror_bd.draw(temp_bd, matrix);
//						mirrorArr.push(mirror_bd);
//					}
					lineArr.push(temp_bd);
				}
				
				//if(mirrorArr.length>0) listMirror.push(mirrorArr);
				list.push(lineArr);
			}
			
//			while(listMirror.length)
//			{
//				list.push(listMirror.shift());
//			}
			
			
			_lib = list;
			updateList();
			_totalFrame = int(data.Frame)-1;
			if(_frameBack==-1 || _frameBack>_totalFrame) _frameBack=_totalFrame;
			_playSpeed = int(data.Time);
			_offsetX = int(data.X);
			_offsetY = int(data.Y);
			_time = Global.Timer;
			
			if(int(data.Direction)==1)
			{
				// 横版驱动
				_2ddriver = true;
			}else{
				_2ddriver = false;
			}
			
			if(data.uv)
			{
				// 配置文件中存在逐帧配置，则启用优化渲染设置
				_uvList = new Array();
				var uv:UVData;
				for each(obj in data.uv)
				{
					uv = new UVData();
					uv.formatJson(obj);
					_uvList.push(uv);
				}
				
				_renderFun = render_cpu;
				_resetMartix = resetMartix_cpu;
				_uvMode = true;
			}else{
				_renderFun = render_base;
				_resetMartix = resetMartix_base;
				_uvMode = false;
				
				_resetMartix();
			}
			
			if(_shadow==null && Number(data.shadowX)>0 && Number(data.shadowY)>0)
			{
				_shadow = new Shape();
				var matr:Matrix = new Matrix();
				matr.createGradientBox(50, 30,0,-25,-15);
				_shadow.graphics.clear();
				_shadow.graphics.beginGradientFill(GradientType.RADIAL,[0,0],[1,0],[0,255],matr);
				_shadow.graphics.drawEllipse(-25, -15, 50, 30);
				_shadow.scaleX = Number(data.shadowX) * _shadowScale;
				_shadow.scaleY = Number(data.shadowY) * _shadowScale;
				_shadow.cacheAsBitmap=true;
				trace('BuildShadow');
			}
			
			if(_onResReady!=null)
			{
				_onResReady();
				_onResReady = null;
			}
			
			_renderFun(true);
			
		}
		
		public function setSWF(data:Object):void
		{
			if(data==null)
			{
				trace("无法加载角色素材"+_swfPath);
				return;
			}
			_lib = data.list;
			updateList();
			_totalFrame = int(data.xml.@Frame)-1;
			if(_frameBack==-1 || _frameBack>_totalFrame) _frameBack=_totalFrame;
			_playSpeed = int(data.xml.@Time);
			_offsetX = int(data.xml.@X);
			_offsetY = int(data.xml.@Y);
			_time = Global.Timer;
			
			if(int(data.xml.@Direction)==1)
			{
				// 横版驱动
				_2ddriver = true;
			}else{
				_2ddriver = false;
			}
			
			if(data.xml.hasOwnProperty('uv'))
			{
				// 配置文件中存在逐帧配置，则启用优化渲染设置
				_uvList = new Array();
				var uv:UVData;
				for each(var obj:Object in data.xml.uv)
				{
					uv = new UVData();
					uv.format(obj);
					_uvList.push(uv);
				}
				
				_renderFun = render_cpu;
				_resetMartix = resetMartix_cpu;
				_uvMode = true;
			}else{
				_renderFun = render_base;
				_resetMartix = resetMartix_base;
				_uvMode = false;
				
				_resetMartix();
			}
			
			if(_shadow==null && Number(data.xml.@shadowX)>0 && Number(data.xml.@shadowY)>0)
			{
				_shadow = new Shape();
				var matr:Matrix = new Matrix();
				matr.createGradientBox(50, 30,0,-25,-15);
				_shadow.graphics.clear();
				_shadow.graphics.beginGradientFill(GradientType.RADIAL,[0,0],[1,0],[0,255],matr);
				_shadow.graphics.drawEllipse(-25, -15, 50, 30);
				_shadow.scaleX = Number(data.xml.@shadowX) * _shadowScale;
				_shadow.scaleY = Number(data.xml.@shadowY) * _shadowScale;
				_shadow.cacheAsBitmap=true;
				trace('BuildShadow');
			}
			
			if(_onResReady!=null)
			{
				_onResReady();
				_onResReady = null;
			}
			
			_renderFun(true);
		}
		
		private var lastRender:uint;
		public function render():void
		{
			if(_renderFun==null) return;
			_renderFun();
		}
		
		private function render_base(flush:Boolean=false):void
		{
			if(_list==null || (!_loop && _nowFrame==_totalFrame) || (!flush && Global.Timer-lastRender<_playSpeed)) return;
			
			lastRender = Global.Timer;
			var cost_time:Number = (lastRender - _time) / _playSpeed;
			
			if (_frame != cost_time)
			{
				_nowFrame = int(cost_time % _list.length);
				_frame = cost_time;
				_bmd.bitmapData = _list[_nowFrame];
				
				if(_frameBackFun!=null && _nowFrame==_frameBack)
				{
					_frameBackFun();
					_frameBackFun=null;
				}
			}
		}
		
		private function render_cpu(flush:Boolean=false):void
		{
			if(!flush && (_list==null || (!_loop && _nowFrame==_totalFrame) || Global.Timer-lastRender<_playSpeed)) return;
			
			lastRender = Global.Timer;
			var cost_time:Number = (lastRender - _time) / _playSpeed;
			
			if (_frame != cost_time)
			{
				_nowFrame = int(cost_time % _list.length);
				_frame = cost_time;
				_bmd.bitmapData = _list[_nowFrame];
				_resetMartix();
				
				if(_frameBackFun!=null && _nowFrame==_frameBack)
				{
					_frameBackFun();
					_frameBackFun=null;
				}
			}
		}
		
		private function updateList():void
		{
			_list = _lib[renderDirection] is BitmapData ? _lib : _lib[renderDirection];
		}
		
		
		private function resetMartix_base():void
		{
			if(_direction<0)
			{
				transformMartix.a = -1;
				transformMartix.ty = _offsetY;
				transformMartix.tx = -_offsetX;
			}else{
				transformMartix.a = 1;
				transformMartix.ty = _offsetY;
				transformMartix.tx = _offsetX;
			}
			
			_bmd.transform.matrix = transformMartix;
		}
		
		private function resetMartix_cpu():void
		{
			if(_direction<0)
			{
				transformMartix.a = -1;
				transformMartix.ty = int(_uvList[renderDirection*(_totalFrame+1)+_nowFrame].offY);
				transformMartix.tx = -int(_uvList[renderDirection*(_totalFrame+1)+_nowFrame].offX);
			}else{
				transformMartix.a = 1;
				transformMartix.ty = int(_uvList[renderDirection*(_totalFrame+1)+_nowFrame].offY);
				transformMartix.tx = int(_uvList[renderDirection*(_totalFrame+1)+_nowFrame].offX);
			}
			_bmd.transform.matrix = transformMartix;
		}
	}
}